home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 176-200 / disk_179 / excption / excption.nro < prev    next >
Text File  |  1992-05-06  |  20KB  |  658 lines

  1. .pl 66
  2. .po  5
  3. .rm 70
  4. .fo //- # -//
  5. .de ma
  6. .br
  7. .nj
  8. .nf
  9. .en
  10. .de te
  11. .ju
  12. .fi
  13. .en
  14. .de cl
  15. .br
  16. .en
  17.  
  18. .ce 8
  19. EXCEPTION HANDLING ROUTINES
  20.  
  21. .ul
  22. Version 0.6
  23. .br
  24. July 6th, 1988
  25. .br
  26.  
  27. Gerald T HEWES
  28. .br
  29. 46 Blvd Inkermann
  30. .br
  31. 92220 NEUILLY S/S
  32. .br
  33. FRANCE
  34. .br
  35.  
  36. .ce
  37. I INTRODUCTION
  38.  
  39.    The purpose of this module is to provide a programmer with a
  40. set of easy to use routines to handle error conditions.
  41. The principle of exception handling is inspired
  42. from Ada(r) exception routines.
  43. Exception handling helps to solve difficult error handling conditions
  44. such as
  45. No more memory, file not open, read/write error.... Usually because of
  46. the difficulty of handling these errors, not much action is done to
  47. correct them. How many programmers faithfully test all their
  48. fread or fwrite results for possible errors?
  49.  
  50.    Exception may be used by any program either as a
  51. flow control or either to capture software errors i.e 68000 exceptions and
  52. Traps. Exception makes the usage of traps very easy from C, since no
  53. assembly code is required.
  54.  
  55.    Experienced programmers might not find anything really new about
  56. these routines and may have already adopted ways to deal with
  57. error handling but I feel it might help
  58. recent Amiga programmers and anybody who is not interested in wrinting
  59. for the (n+1)th time similar procedures.
  60.  
  61.    These routines are very different from the GOMF software. You may
  62. have as many "protected code" zones in your program as you want,
  63. and you dispose of
  64. a mean to propagate easily errors upward if you cannot fix the problem
  65. at a low level (usually the case for fwrites's). In any case, no actions
  66. are taken
  67. whatsoever, control is simply passed to your local (context wise)
  68. handling routine. Your task is not suspended. All your handling
  69. routines are in user mode with multitasking enabled.
  70. .bp
  71. 1.2 Contents
  72. .ma
  73.  
  74. I   INTRODUCTION
  75.  
  76. II  EXCEPTION HANDLING
  77.  
  78.      2.1 Introduction to Exception Handling
  79.       2.1.1 Top Level
  80.       2.1.2 Resource Protection
  81.      2.2 How to Use Excption
  82.       2.2.1 ExcpGlobal
  83.       2.2.2 MAIN
  84.       2.2.3 ExcpDeclare
  85.       2.2.4 BEGIN/EXCEPTION/END
  86.       2.2.5 Variables
  87.       2.2.6 Excption Class Numbers
  88.      2.3 Important Data
  89.  
  90. III ORGANISATION
  91.  
  92.      3.1 Files
  93.      3.2 Macros
  94.  
  95. IV  IMPROVEMENTS
  96.  
  97. V   CONCLUSION
  98.  
  99. VI  BIBLIOGRAPHY
  100.  
  101.  
  102. .te
  103. .bp
  104. .ce
  105. II EXCEPTION HANDLING
  106.  
  107. 2.1 Introduction to Exception Handling
  108.  
  109.    Error Management and complexe human interfaces are always a difficult
  110. problem in a program, and no perfect solution exists. Exception handling
  111. is one way to alleviate the problem, but does not solve it. These
  112. techniques were originally applied on a sun workstation for an interactive
  113. program. Port was then done on the Amiga, with a better interface.
  114. Originally, the ideas commes from Ada's(r) exception handling but has
  115. been slightly modified to take into account C's differences. A first
  116. difference is the use of Macros, these do not have the power of defined
  117. keywords in Ada. The second major difference stems from
  118. the fact that Ada(r) protects you from every error condition possible,
  119. while this library will only recuperate errors which normally give
  120. birth to "SoftWare Error/Task Held". Thus you still enjoy fireworks
  121. for fatal errors destroying the operation of the system.
  122.  
  123.    What is exactly exception programing? In gross terms, algorithms
  124. usually describe the normal flow of operations. Unfortunately,
  125. exceptional activities can happen and have to be treated. If nothing
  126. is provided by the language, the programmer has to introduce many
  127. control statements to take into account these abnormal conditions.
  128. The programer usually ends up with a code twice the size of the
  129. original algorithm. This has two inconvenients: the code is no longer
  130. clear because of the overhead, and it is hard to follow the flow of
  131. a normal program. Exception programing tries to solve this problem.
  132. The principle is clear, write the normal code, and add at the end of
  133. this code the code describing those exceptional events. Each part
  134. being separate, programs get much clearer.
  135.  
  136.    Lets consider a simple problem. You want to translate from cartesian
  137. coordinates to polar coordinates. The method in the first quadrant is
  138. theta = atan (y/x). This formula is true for x <> 0, if x = 0, then
  139. theta = pi/2. With no exceptions this gives:
  140.  
  141. .ne 30
  142. .ma
  143.    if (x != 0)
  144.     {
  145.       z     =  y/x;
  146.       theta = atan(z);
  147.     }
  148.    else
  149.     theta = pi/2;
  150. .te
  151.  
  152.    The normal flow is lost in the if condition. Exception programing
  153. would prefer:
  154.  
  155. .ma
  156. ADA:
  157.   begin
  158.    z     := y/x;
  159.    theta := atan(z);
  160.   exception
  161.    when NUMERIC_ERROR =>
  162.     theta = pi/2;
  163.    when others =>
  164.     PUT("UNKNOWN ERROR");
  165.     raise ERROR;
  166.   end;
  167.  
  168. This is simply translated into:
  169.  
  170. C:
  171.   BEGIN
  172.    {
  173.     z     = y/x;
  174.     theta = atan(z);
  175.    }
  176.   EXCEPTION
  177.    {
  178.    switch(Eclass)
  179.     {
  180.      case ZERO_DIVIDE   : theta = pi/2; break;
  181.      default            : puts("UNKNOWN ERROR"); RAISE(ERROR);
  182.     }
  183.    }
  184.   END;
  185. .te
  186.  
  187.  
  188.    This may not seem remarkable on a simple example, but it can become
  189. very handy in real life problems which usually are not coded in 6 lines.
  190.  
  191.    The idea is simple. In a protected region, you describe the
  192. simple algorithm. Automatic errors, or software detected ones can
  193. provoke an "Exception" which will cause the program to abandon
  194. the protected region to execute the handler region instead. Either
  195. this handler is qualified to handle the exception and thus
  196. controls resumes after the protected/handler block, or the handler
  197. can decide to propagate the exception to the next handler.
  198.  
  199.    This is the second advantage of Exception programing. Protected
  200. blocks can be inscribed inside each other like russian dolls. An
  201. exception can thus be handled, at the most convenient level, and
  202. necessary action while "poping" out can be performed, like liberating
  203. some resources allocated in the normal flow.
  204.  
  205.    This is why Exception handling is very practical in riche
  206. environments like the amiga. For example, you can isolate
  207. all the function calls in your main Wait loop with a protection zone.
  208. If anything happens, including an abort request, control resumes
  209. back to your main loop where you can decide what to do. Thus your
  210. main Wait loop can be seen as a "top level" for your program. Deep
  211. in your code, if you get stuck, a raise to the "top level" is always
  212. available.
  213.  
  214.   Here are a few possible scenarios:
  215.  
  216. 2.1.1 Top Level
  217.  
  218. .ma
  219.    forever
  220.     {
  221.       Wait();
  222.        if (EXIT) break;
  223.       BEGIN
  224.        {
  225.         switch() { Some Dangerous Functions }
  226.        }
  227.       EXCEPTION
  228.        {
  229.         switch(Eclass) { .... }
  230.        }
  231.       END
  232.     }
  233. .te
  234.  
  235. 2.1.2 Resource Protection
  236.  
  237.    In this construction, you cannot leave the area without liberating
  238. your resource, even if the error will be handled at higher level.
  239.  
  240. .ma
  241.    Allocate-Resource
  242.  
  243.    BEGIN
  244.     {
  245.       Use-Resource (Dangerous Area)
  246.       Liberate-Resource
  247.     }
  248.    EXCEPTION
  249.     {
  250.       Yell
  251.       Liberate-Resource
  252.       Propagate-Error-If-Necessary
  253.     }
  254.    END
  255. .te
  256.  
  257. 2.2 How to Use Excption
  258.  
  259.    In order to use all the exception handling routines you need to include
  260. the following file:
  261. .br
  262.  
  263. #include "local:excption.h"
  264. .br
  265.  
  266.    For examples of the use of the exception handler consult the two
  267. supplied examples "essai.c" and "fact.c".
  268.  
  269. 2.2.1 ExcpGlobal
  270.  
  271.    This static definition is needed once in your code. It reserves
  272. a structure needed by the handling code to operate. ExcpGlobal
  273. is implemented as a macro.
  274.  
  275. 2.2.2 MAIN
  276.  
  277.    The first protected block, called throughout this document "top level
  278. block" is of a particular form. This block does not need a declaration
  279. statement of the form ExcpDeclare, all relevant data is already declared
  280. in the ExcpGlobal structure. The format of the first protected is
  281. MAIN/EXCEPTION/OUT. The form BEGIN/EXCEPTION/END cannot be used.
  282. This is very important because the MAIN and OUT macro perform the
  283. necessary initialization and conclusion functions.
  284.  
  285.    Here is an example:
  286. .ne 17
  287. .ma
  288.   main()
  289.    {
  290.      other declarations ...
  291.  
  292.      some code ...
  293.  
  294.      MAIN
  295.       {
  296.         protected code ...
  297.       }
  298.      EXCEPTION
  299.       {
  300.         Exception handling code ...
  301.       }
  302.      OUT
  303.  
  304.      yet more code ...
  305.  
  306.    }
  307. .te
  308.  
  309.    Note: the toplevel does not need to be in the main function.
  310.  
  311. 2.2.3 ExcpDeclare
  312.  
  313.    Declare an exception handling routine in the current function. This
  314. is a macro which hides the necessary declaration of hidden variables. As
  315. such it must be used before any program statement. Currently only
  316. one protected zone may exist in one routine.
  317.  
  318. 2.2.4 BEGIN / EXCEPTION / END
  319.  
  320.    Exception handling is based on the notion of protected blocks of
  321. statements. In the current implementation, only one block per function
  322. is allowed. This in practice has not been an handicap and may be changed
  323. in future releases. This limitation only stems from the Macros used, not
  324. from any limitation by the exception handling routines. The syntax is:
  325.  
  326. .ne 18
  327. .ma
  328.   toto()
  329.    {
  330.      ExcpDeclare;
  331.      other declarations ...
  332.  
  333.      some code ...
  334.  
  335.      BEGIN
  336.       {
  337.         protected code ...
  338.       }
  339.      EXCEPTION
  340.       {
  341.         Exception handling code ...
  342.       }
  343.      END
  344.  
  345.      yet more code ...
  346.  
  347.    }
  348. .te
  349.  
  350. In the some code block, nothing is changed, so  put your faithful code in
  351. this area. No niceties are provided.
  352.  
  353. In the protected code block, you have acces to the following functions:
  354.  
  355. .ne 4
  356. .ma
  357.    RAISE(ExcpClass)     : raise an error.
  358.    BLOW(ExcpClass)      : raise/blow to top level handler.
  359. .te
  360.  
  361.    Control will be  transferred
  362. to the exception handling block. Your exception will then be handled
  363. by this code. Either the exception is propagated with a RAISE
  364. statement to upper levels, or it is handled locally. If it is handled
  365. locally, execution will resume in the yet more code area. If no
  366. exception occur in the protected code block, control continues normally
  367. in the yet more code area.
  368.  
  369.    These two function may also be called from any subroutines called
  370. in the protected code block. They may not be called from another task
  371. if a task is created in the protected code block.
  372.  
  373.    A return statement is not allowed in the protected code area, and
  374. the exit function is not recommended. Long Jumps are not recommended:
  375. Exception handling is long jumping, stay consistent. Goto's
  376. are not allowed to span in or out of  the protected code block.
  377. All those limitations come from the fact that you have to execute
  378. the END code before leaving the function. The END code, disables the
  379. current context and restores the previous (upper) one. If you want
  380. to LongJmp, you can modify your code to use instead the propagation
  381. mechanism.
  382.  
  383. In the handling code block you should test the exceptions and either
  384. handle them locally, or propagate them upward. You have access to the
  385. same functions:
  386.  
  387. .ne 4
  388. .ma
  389.   RAISE(ExcpClass)   : raise an error to the next level
  390.   BLOW(ExcpClass)    : raise/blow to top level handler.
  391. .te
  392.  
  393.    RAISE has the same operation as when employed in
  394. the protected code block, but will transfer control to the next (upper)level
  395. handling code, raising the error. Once raised, there is no way to resume
  396. processing in the yet more code block.
  397.  
  398.    The same restrictions apply to the handling code block as to the
  399. protected block concerning: goto,return,exit,_exit,longjmp,...
  400.  
  401. 2.2.5 Variables
  402.  
  403.    The following variables are defined in the Handler routines:
  404.  
  405. .ma
  406.    Eclass    : Exception class of the exception
  407. .te
  408.  
  409.    In the exception handling zone, Eclass contains the exception number
  410. being treated. Be sure to check this number because the system may generate
  411. numbers that you have not planned for. For example the system traps all
  412. 68000 errors, Eclass is then the Trap number as defined by Motorola.
  413. This is very useful for program debugging since the code traps bus errors
  414. which usually indicate pointer troubles.
  415.    If you do not handle the error locally, the call RAISE(Eclass) is
  416. a must. By doing this you can correct the exception at a higher level.
  417.  
  418. 2.2.6 Excption Class Numbers
  419.  
  420.    All exceptions have an exception class number which serves as an
  421. identification. Numbers from 1-65535 are reserved values which may not
  422. be used. Under the current version words 1-1023 are reserved for
  423. 68000 related problems. Check the values defined in excption.h
  424. for more information. This range covers 68000 exception, 68000 traps
  425. and could cover 68000 interrupts. Range 1024-2047 are global
  426. types of error which are also declared in exception.h. Most of
  427. these declarations are inspired from Ada.
  428.    Range 2048-65535 are reserved for libraries. These values cannot
  429. be used for an application.
  430.    Application must use numbers over 65536.
  431.  
  432.    The programmer must take great care to avoid using the same number
  433. for two different exception. Unfortunately, this has to be done by
  434. hand. This is a major difference with Ada. Two, incompatible ways
  435. can be used for allocating these exception class numbers.
  436.  
  437.    The first method is to #define all your exception class numbers, in
  438. a fashion similar to the handler itself. This is the most simple way
  439. but has the inconvenience of being dangerous. Two exceptions might
  440. use the same number. Coherence has to be maintained by the programmer.
  441. This method is not recommended for large programs.
  442.  
  443.    The second method is to use the allocating function AllocException().
  444. AllocException returns a unique exception number starting from
  445. 65536. This automatically insures the coherence of all part of a large
  446. program. Its inconvenient is that it requires more code from the
  447. programmer point of view.
  448.  
  449.    The current algorithm for allocation is rudimentary. You can only
  450. call AllocException with an argument of -1. This means, as for many
  451. Amiga allocating function, that you have no preference for the number
  452. allocated. Allocation starts from 65536, and increments by one at
  453. every call. FreeAllocation is for decoration since it does nothing.
  454. I might consider providing better allocation mechanism in the future,
  455. but for the moment I see no use for it.
  456.  
  457. 2.3 Important Data
  458.  
  459.    I add this paragraph since I do not have the appropriate documentation.
  460. If you catch an error report it.
  461.  
  462.    When a 68000 exception occurs, the Amiga OS detects it and treats it.
  463. The Excption 68000 number is calculated and pushed down on the SSP
  464. stack after the usual exception frame. Control is then given back, in
  465. superuser mode, to the code pointed by task->tc_TrapCode. When using
  466. the exception handling routines, this points to my assembler EIExcpHandler
  467. routine.
  468.    This routine tests if the code is running on a 68000. If yes,
  469. the SSP stack is corrected by 6+4 bytes for simple exception, and
  470. 14+4 bytes for bus or address exceptions. The +4 comes from the
  471. Long Word pushed by the Amiga Os.
  472.    If the code is running on a 68010 or +, operations are very different.
  473. The handler, fetches the format number at SSP+8 and corrects the
  474. SSP by the following values:
  475. .br
  476. Values in 16-bit words
  477. .ne 8
  478. .ma
  479.  
  480.                         Format
  481.  
  482. 0   1   2   3   4   5   6   7   8   9   a   b   c   d   e   f
  483. -------------------------------------------------------------
  484. 4   4   6   0   0   0   0   0  29  10  16  46   0   0   0   0
  485. .te
  486.  
  487.  
  488.    As usual, 4 bytes have to be added to these numbers. These table may
  489. be inaccurate since I do not have a good documentation on these
  490. values.
  491.    After correcting the SSP stack, the handler passes in User Mode,
  492. and calls the EIEndHandler (a C function) with the exception number
  493. (provided by Amiga OS) as sole argument.
  494. .bp
  495. .ce
  496. III ORGANISATION
  497.  
  498.  
  499. 3.1 Files
  500.  
  501.    To compile programs you need to assign local: to contain
  502. excption.lib, excption.h and boolean.h. You must have directory named
  503. private with the excppriv.h file in it.
  504. Your programs
  505. need to include the definition file "local:excption.h".
  506.  
  507.    As of version 0.4, all routines are compiled seperately. For Lattice
  508. users, these object modules are all joined in the excption.lib
  509. lattice library. To compile your code all you need to do id to add
  510. .br
  511. LIB local:excption.lib
  512. .br
  513. to your blink command.
  514. Currently the files are organised as follows:
  515.  
  516. .ma
  517. -excption.h   : file which your code needs to include to use the
  518.                 exception routines.
  519. -boolean.h    : file included by excption.h
  520. -excption.lib : library file to use with blink.
  521. -excption.man : this file
  522. -excption.doc : documentation on defined functions
  523. -EI*.c        : source for defined functions
  524. -excphand.a   : assembler handling routine
  525. -essai.*      : A good example of use of exceptions
  526. -fact         : A bad example, for different reasons but instructive.
  527. -README       : text file describing the contents and the version
  528.                 differences.
  529. .te
  530.  
  531. 3.2 Macros
  532.  
  533.    This is a resume of the available Macros, Variables and Functions:
  534.  
  535. .ma
  536. BEGIN        : M start of a protected block
  537.  
  538. BLOW         : M give control to outmost handler
  539.  
  540. Eclass       : V exception class
  541.  
  542. END          : M end of handler block
  543.  
  544. ExcpAlloc    : F allocate an unique exception class number
  545.  
  546. ExcpDeclare  : M declare an excption block in a routine
  547.  
  548. EXCPDISABLE  : M disable processor error handling
  549.  
  550. EXCPENABLE   : M enable back processor handling (Default Mode)
  551.  
  552. ExcpFree     : F free an allocated exception class number
  553.  
  554. ExcpGlobal   : M declare a global structure needed by exception
  555.  
  556. EXCEPTION    : M end of protected block, beginning of handler
  557.  
  558. MAIN         : M start of outmost protected block (replaces BEGIN)
  559.  
  560. OUT          : M end of outmost  protected block (replaces END)
  561.  
  562. RAISE        : M Propagate exception to inmost handler
  563. .te
  564. .bp
  565. .ce
  566. IV IMPROVEMENTS
  567.  
  568.    The following ideas will be investigated in further releases:
  569.  
  570. -Signaling to the User that an 68000 exception has occured. Useful
  571. for debugging.
  572.  
  573. -Final Catch of 68000 exceptions and user notice at the top level.
  574.  
  575. -Provide a mean for the program to call a supplied function
  576. before giving control to the local exception handling code
  577.  
  578. -Run time library version
  579.  
  580. -Stack checking before saving context
  581.  
  582. -Tracing of entrance into protected blocks in a debug version.
  583.  
  584.    Discussing with some Ada compilers makers was instructive. Their
  585. point of view was that they do not want exception handling to lose
  586. time in normal operations. On the other hand they are willing
  587. to consecrate a big amount of time to solve where the control
  588. has to resume when an exception is raised. This is radically
  589. different from my implementation with longjmps. Each
  590. BEGIN statement needs to save the environment which is slow.
  591. When an exception is raised, restoring the environment is not
  592. costly. Those Ada compiler makers have thus used a completely
  593. different approach. At compile time they note where each
  594. handler is active. When an exception occurs, the program tests where
  595. the exception occured, and thus where to branch.
  596. It is not necessary to save the environment at each begin.
  597. To achieve this you need to have exception handling defined
  598. in the language, not out of it. Which is best?
  599.  
  600.    Performances:
  601.  
  602.    Version 0.5 seemed to have no bugs. There are two things to watch.
  603. Bad bugs will crash the system, because they destroy the environment.
  604. Nothing can be done by software. The exception handler is fairly
  605. safe since its always checks its data coherence, if an error occurs,
  606. an exit(200) or exit(201) is performed. These two exits have
  607. always been due to unmatched BEGIN/EXCEPTION/END statements, even
  608. in spots far from where the program stopped. Check those if this
  609. happens to you.
  610. .bp
  611. .ce
  612. V CONCLUSION
  613.  
  614.  
  615.    Exception programming is a very powerful tool, but should
  616. be carefully used. 68000 Exceptions should stay exceptional.
  617. Keep in mind that an exception declaration in a routine
  618. consumes about 40 bytes in the stack. Recursive functions have
  619. to be carefully examined. A good knowledge of LongJumping although
  620. not necessary can help resolve all kinds of conflicts you may run
  621. into. This code can be particularly helpful in the debugging period,
  622. but is unfortunately incompatible with Fred Fish DBUG macros. In
  623. general, this software does not like longjmps.
  624.  
  625.    Because of its similarity with Ada(r) Exception handling, consulting
  626. a manual on Ada, and mostly on how to use its exception mechanism is
  627. a recommended idea.
  628.  
  629. .bp
  630. .ce
  631. VI BIBLIOGRAPHY
  632.  
  633. .br
  634. * [ADA 83]
  635. .br
  636. REFERENCE MANUAL FOR THE ADA(r) PROGRAMMING LANGUAGE ---
  637. ANSI/MIL-STD 1815 A
  638. .br
  639. * [BEHM 86]
  640. .br
  641. NOTES SUR LE TRAITEMENT DES EXCEPTIONS --- Patrick BEHM, BULL, Louveciennes
  642.  
  643.  
  644.  
  645.  
  646.  
  647.  
  648.  
  649.  
  650.  
  651.  
  652.  
  653.  
  654.  
  655. .br
  656. (r) ADA is a  registered trademark of the U.S. Government. Ada Joint Program
  657. Office.
  658.